The Database Shell is a complete database application. It allows single-user access to a local database file or a multi-user access to an AppleShare database file. It supports commands to navigate and modify clusters (records) in a database. It also provides you with a simple query window, a page preview window & a simple report generator.
A Customer Database Example has been implemented in the shell to give you a working application to study. When you want to build your own application with the shell, delete the Customer and CustomerE classes and create your own subclasses of Cluster and Editor. Everything will work automatically if you follow the conventions outlined in the rest of this document.
Although several classes from the Document Shell were incorporated into this Database Shell, we did not use the multi-document features of the Document Shell because this example worked best with a single document, multiple table model. Relational operations are not a part of this example, although the structure is set up so that they could be easily added for cross-table queries. (An exercise for the reader?!)
HOW TO USE IT
-------------
Ñ Cluster Class
The structure of your database is defined by creating subclasses of class Cluster. For each subclass of Cluster, one table will be created in the database with the name of that class. Instances of the class are stored as clusters (records) in the table; therefore, you could say that the attributes of the class are the "fields" of each record.
The subclass "DBHeader" defines a special table that will be a part of all databases created with this shell. This table contains only one cluster, a header with application-specific information about each database. You should modify the attributes of this class to suit your needs. In the Customer database example, for instance, the customer id attribute was added to hold the last unique id assigned to customer records in the database. IMPORTANT NOTE: Don't touch the "header id" attribute; the Database Shell assumes this is always there.
The class attribute "Key & Option List" should contain two lists. The first is a list of attribute names that should be used as keys in the database. The second is a list of lists; each item is a list of option strings for the key in the corresponding position in the first list. See the Customer class for an example.
The class attribute "Report List" should contain a list of instances of class Report or its subclasses. That is, open the attribute, make sure its type is list, and click the graphic check box; to create an instance of Report, click in space to create a new list item, open the list item and select a type of Report or one of its subclasses. You may then need to enter values for one or more of the attributes; for instance, for the Table Report subclass, you should fill in the name and the format list attributes. More details about reports are explained below..
Ñ Editor Class
For each Cluster subclass that you create, there should be a corresponding Editor subclass. In the example, the Customer class has a corresponding CustomerE class. You should follow the naming convention - that is, to use the name of the Cluster subclass with an "E" appended at the end.
Use the Application Builder to create an instance of your Editor subclass and draw a data entry form by adding window items. Use the "Set Defaults" button to make this data entry form the default for that class.
If you simply name the window item the same name as the attribute you want its value to be saved to, the Database Shell will automatically save values from the entry form to the cluster (record) being edited and vice-versa. This is accomplished by defining the methods "Get Value", "Set Value" and "Clear Value" for each type of Window Item subclass; for instance, "Get Value" behaves as follows:
<Edit Number> returns a real or an integer
<Edit Text> & <Scroll Text> return a string
<Radio Set> & <Pop-up Menu> return an index
<Scroll List> returns an index list
<Check Box> returns a Boolean
If you define your own subclasses of Window Item that you want to be used for data entry, simply define "Get Value", "Set Value" and "Clear Value" methods for it, and it will fit smoothly into the default processing of the Database Shell.
Ñ Report Class
The Report class is a generic class for setting up and printing a report. It is based somewhat on the Printer class from the Document Shell. You can create a subclass of Report and overshadow the "draw header", "draw cluster" & "draw footer" methods to create your own report formats.
Which clusters that are included in the report depends on the last query you performed. They are stored in the Found List attribute of the Editor window, and are placed in the cluster id list attribute of the Report instance. A value of NULL means that all clusters should be printed (Find All).
The class attribute "format list" is provided to store information about how to format different reports of the same type. You may choose any representation or none at all, as long as the methods in your Report subclass understand it.
We have provided the Table Report subclass, which prints selected attributes of each cluster on each line of the report. The format list in this case is a list of triples; each triple consists of the name of the attribute to be reported, the width of its column in pixels and its justification (0=left, 1=center, and -1=right). By default, the Table Report prints the names of all the attributes in the list as the header of each page, and the page number as the footer.
For example, the Report List class attribute of the Customer class contains two instances of Table Report. One is named "Phone List" and produces a printout of each customer's id, full name and phone number. The other is named Address List and produces a printout of each customer's full name and address.
Ñ PagePreview Class
When page preview is invoked, Report is asked to generate the report one page at a time. Each page is then drawn on the screen instead of the printer.
Ñ QueryWind, AttrQueryWind and Query Classes
When you select Find from the menu, a QueryWind is opened. This allows you to specify search and sorting criteria. You select the table to search with the Radio Buttons at the top of the window. You enter the search criteria by selecting an attribute name from the list, then the comparison operator, then typing in the comparison value in the edit box and pressing the Append button. You can also press the AND and OR button operators and build up a complete query statement; queries are processed from left to right. When you are done specifying the query, press the Find button.
The methods for doing the searching and comparing are all found in the Query class. All of the methods EXCEPT "process attr query" assume that the attribute being searched for is a key value. The "retrieve" method makes sure that, in a multi-user situation, locked clusters are skipped.
The method "process attr query" allows you to search on any attribute of the instance stored in the cluster, not just the key values. It works in conjunction with the AttrQueryWind. By default, this is not used in the Customer Database Example. To see it in action, modify the Universal method "query window" to return an instance of AttrQueryWind instead of QueryWind. Searching without keys is, as you might guess, a bit slower, but may not be as bad as you think.
Ñ Edit Number Class
This is just a useful subclass of Edit Text that only allows the user to type numbers into it. Take a look at the Key method to see how this is accomplished.
NOTES
-----
You must create a new database whenever you create, modify or delete a Cluster subclass.
To save time, methods in the Query classes return both cluster instances and ids. If a query returns a huge number of clusters, you may run out of memory. To overcome this problem, modify the "read all ????" methods to make sure that the cluster instances are not saved. You will also need to modify the "process query" method to read each instance based on the cluster id.
The query class assumes that all the keys are sorted in ascending order. You will need to modify the comparison routines if you plan to use descending keys.
A multi-user database file MUST be an AppleShare File.
When you edit a cluster, it gets locked and saved automatically. Locked clusters are inaccessible to other users.